package webmarket.jpacontrollers;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.EntityType;

import org.apache.commons.lang3.StringUtils;

import webmarket.common.CommonMethods;
import webmarket.model.User;

public class UserJpaController extends JpaControllerBase<User> {
	/**
	 * 
	 */
	private static final long serialVersionUID = -309733597719437493L;

	public UserJpaController() {
		super(User.class);
	}

	public User getCurrent() {
		String currentUserName = CommonMethods.getCurrentUserName();
		return getByUsername(currentUserName);
	}

	public User getByUsername(String username) {
		EntityManager em = getEntityManager();
		User userEntity = null;
		try {
			CriteriaBuilder cb = em.getCriteriaBuilder();
			CriteriaQuery<User> cq = em.getCriteriaBuilder().createQuery(User.class);
			cq.select(cq.from(User.class));
			EntityType<User> user = em.getMetamodel().entity(User.class);
			Root<User> root = cq.from(user);
			cq.select(root);
			Expression<String> usernameexp = root.get(user.getDeclaredSingularAttribute("username", String.class));
			cq.where(cb.equal(usernameexp, username));
			TypedQuery<User> q = em.createQuery(cq);
			userEntity = q.getSingleResult();
		} catch (NoResultException e) {
			
		} finally {
			em.close();
		}
		return userEntity;
	}

	public boolean userExists(String username) {
		EntityManager em = getEntityManager();
		boolean exists = false;
		try {
			CriteriaBuilder cb = em.getCriteriaBuilder();
			CriteriaQuery<User> cq = em.getCriteriaBuilder().createQuery(User.class);
			cq.select(cq.from(User.class));
			EntityType<User> user = em.getMetamodel().entity(User.class);
			Root<User> root = cq.from(user);
			cq.select(root);
			Expression<String> usernameexp = root.get(user.getDeclaredSingularAttribute("username", String.class));
			cq.where(cb.equal(usernameexp, username));
			TypedQuery<User> q = em.createQuery(cq);
			//getSingleResult() calls getResultList() internally -> no performance loss, easier
			exists = !q.getResultList().isEmpty();
		} finally {
			em.close();
		}
		return exists;
	}

	public List<User> getUsers(String userName, String sortCol, String sortDir, int limit, int offset) {
		EntityManager em = getEntityManager();
		List<User> results;
		try {
			CriteriaBuilder cb = em.getCriteriaBuilder();
			CriteriaQuery<User> cq = em.getCriteriaBuilder().createQuery(User.class);
			cq.select(cq.from(User.class));
			EntityType<User> user = em.getMetamodel().entity(User.class);
			Root<User> root = cq.from(user);
			cq.select(root);
			Expression<String> usernameexp = root.get(user.getDeclaredSingularAttribute("username", String.class));
			cq.where(PredicateBuilder.createLikePredicate(cb, usernameexp, userName));
			if (StringUtils.isBlank(sortCol)){
				sortCol="username";
			}
			Order order=super.getOrder(sortCol, sortDir.equals("desc"), em, root);
			cq.orderBy(order);
			
			TypedQuery<User> q = em.createQuery(cq);
			
			q.setMaxResults(limit);
			q.setFirstResult(offset);
			
			results = q.getResultList();
			
		}
		finally {
			em.close();
		}
		return results;
	}
	
	public int getCount(String userName){
		int count;
		EntityManager em = getEntityManager();
		try {
			CriteriaBuilder cb = em.getCriteriaBuilder();
			CriteriaQuery<Long> cq = em.getCriteriaBuilder().createQuery(Long.class);
			EntityType<User> user = em.getMetamodel().entity(User.class);
			Root<User> root = cq.from(user);
			Expression<String> usernameexp = root.get(user.getDeclaredSingularAttribute("username", String.class));
			cq.where(PredicateBuilder.createLikePredicate(cb, usernameexp, userName));
			count=super.getCount(PredicateBuilder.createLikePredicate(cb, usernameexp, userName), em, cq, root);
		}
		finally {
			em.close();
		}
		return count;
	}
	
	
	
}
